const fs = require("fs");
const path = require("path");
const fse = require("fs-extra");
const inquirer = require("inquirer");
const sysPath = require("path");
const { execSync } = require("child_process");
const os = require("os");
const handleReactTemplate = require("./handleReactTemplate.js");
const handleVueTemplate = require("./handleVueTemplate.js");
const handleVue3Template = require("./handleVue3Template.js");

let allTemplates;
try {
  allTemplates = fs.readdirSync(path.resolve(__dirname, "../packages"));
} catch (e) {
  allTemplates = require("./allTemplates.json");
}
const templateChoices = [
  { name: "React", value: "react", handleFun: handleReactTemplate },
  { name: "Vue 2", value: "vue", handleFun: handleVueTemplate },
  // { name: "Vue 3", value: "vue3", handleFun: handleVue3Template },
];
const batchFlag = process.argv.slice(2)[0] === "--batch";
const prompts = [
  {
    type: "list",
    name: "templateType",
    message: "请选择模板类型",
    choices: [...templateChoices, { name: "全部", value: "all" }],
  },
  {
    type: "input",
    name: "pluginType",
    message: "请输入插件类型(config.json中的type字段)",
    validate: (pluginType, answer) => {
      let { templateType } = answer;
      if (pluginType.trim() === "") {
        return "type字段不可为空";
      }
      if (templateType !== "all") {
        let result = validate(pluginType, templateType);
        if (result === false) {
          return "该插件已存在，请重新输入type并选择正确的模板类型";
        }
      } else {
        for (let i = 0; i < templateChoices.length; i++) {
          let result = validate(pluginType, templateChoices[i].value);
          if (result === false) {
            return "该插件已存在，请重新输入type并选择正确的模板类型";
          }
        }
      }
      return true;

      function validate(pluginType, templateType) {
        let newFolderFullName = `${pluginType}-${templateType}-plugin`;
        if (
          allTemplates.includes(newFolderFullName) &&
          process.env["sdataPlugins"] === "true"
        ) {
          return false;
        }
        if (process.env["sdataPlugins"] !== "true") {
          if (fs.existsSync(path.resolve(process.cwd(), newFolderFullName))) {
            return false;
          }
        }
      }
    },
  },
  {
    type: "list",
    name: "process",
    message: "主渲染区域是否需要逻辑控制",
    choices: [
      { name: "是", value: true },
      { name: "否", value: false },
    ],
  },
  {
    type: "list",
    name: "designConfiguration",
    message: "是否需要配置项渲染区域",
    choices: [
      { name: "是", value: true },
      { name: "否", value: false },
    ],
  },
];
const repeatPrompts = [
  {
    type: "list",
    name: "add",
    message: "是否继续添加一个渲染区域",
    choices: [
      { name: "是", value: true },
      { name: "否", value: false },
    ],
  },
  {
    type: "input",
    name: "viewType",
    message: "请输入视图类型（请严格按照小驼峰格式书写）",
    when: answer => answer.add === true,
    validate: viewType => {
      if (viewType.trim() === "") {
        return "type字段不可为空";
      }
      let views = viewAnswer.map(item => {
        return item.viewType;
      });
      if (viewType === "designConfiguration") {
        return "该类型为保留字，不可使用，请输入其他类型";
      }
      if (views.includes(viewType)) {
        return "该渲染区域类型已存在，请重新输入正确的渲染区域类型";
      }
      return true;
    },
  },
  {
    type: "list",
    name: "process",
    message: "该视图是否需要逻辑控制",
    when: answer => answer.add === true,
    choices: [
      { name: "是", value: true },
      { name: "否", value: false },
    ],
  },
];
let viewAnswer = [];
if (batchFlag) {
  try {
    const definitionJson = require(path.resolve(
      process.cwd(),
      "definitions.json"
    ));
    definitionJson.forEach(async item => {
      await handleAnswer(item.answer, item.viewAnswer);
    });
  } catch (e) {
    console.log(
      "请将定义文件命名为definitions.json,放在当前文件夹下，定义格式为" +
        "[\n" +
        "  {\n" +
        '    "answer": {\n' +
        '      "templateType": "all"|vue|react,\n' +
        '      "pluginType": "test"\n' +
        "    },\n" +
        '    "viewAnswer": [\n' +
        "      {\n" +
        '        "viewType": "main",\n' +
        '        "process": true\n' +
        "      },\n" +
        "      {\n" +
        '        "viewType": "designConfiguration",\n' +
        '        "process": false\n' +
        "      }\n" +
        "    ]\n" +
        "  }\n" +
        "]"
    );
  }
} else {
  inquirer.prompt(prompts).then(answer => {
    let callback = async res => {
      if (res.add) {
        viewAnswer.push({
          viewType: res.viewType,
          process: res.process,
        });
        viewQuestionFun(res => {
          callback(res);
        });
      } else {
        await handleAnswer(answer, viewAnswer);
      }
    };
    if (answer.process) {
      viewAnswer.push({
        viewType: "main",
        process: true,
      });
    } else {
      viewAnswer.push({
        viewType: "main",
        process: false,
      });
    }
    answer.designConfiguration &&
      viewAnswer.push({
        viewType: "designConfiguration",
        process: false,
      });
    viewQuestionFun(res => {
      callback(res);
    });
  });
}

function viewQuestionFun(callback) {
  inquirer.prompt(repeatPrompts).then(answer => {
    callback(answer);
  });
}

const generateUUID = () => {
  let d = new Date().getTime();
  return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function (c) {
    let r = (d + Math.random() * 16) % 16 | 0;
    d = Math.floor(d / 16);
    return (c === "x" ? r : (r & 0x3) | 0x8).toString(16);
  });
};

async function handleAnswer(answer, viewAnswer) {
  const startCommond = os.type() === "Darwin" ? "open" : "start";
  let outterPath = "";
  if (answer.templateType === "all") {
    for (let i = 0; i < templateChoices.length; i++) {
      const templateType = templateChoices[i].value;
      outterPath = await generateTemplate(
        Object.assign(answer, { templateType: templateType }),
        viewAnswer,
        true
      );
    }
    const tipContent =
      "请将mockData.js和adapter.js的内容补充完整，并复制到对应的文件夹,之后删除src文件夹及本tips文件";
    fs.writeFileSync(path.resolve(outterPath, "tips.txt"), tipContent);
    if (!batchFlag) {
      execSync(`${startCommond} ${outterPath}`);
      execSync(`${startCommond} ${outterPath}/tips.txt`);
      execSync(
        `${startCommond} ${outterPath}/src/components/development/mockData.js`
      );
      execSync(
        `${startCommond} ${outterPath}/src/utils/handlePlatform/adapter.js`
      );
    }
  } else {
    await generateTemplate(answer, viewAnswer);
  }
}

async function generateTemplate(answer, viewAnswer, isAll) {
  let { pluginType, templateType } = answer;
  let newFolderFullName = `${pluginType}-${
    templateType === "react" ? "" : templateType + "-"
  }plugin`;

  let basepath = path.resolve(__dirname, `./${newFolderFullName}`);
  mkdirSync(basepath);
  await fse.copy(path.resolve(__dirname, `./${templateType}`), basepath);
  const configJson = require(`${basepath}/pluginTemp/config.json`);
  const packageJson = require(`${basepath}/package.json`);
  configJson.id = generateUUID();
  configJson.type = pluginType;
  packageJson.name = newFolderFullName;
  fs.writeFileSync(
    path.resolve(__dirname, `${basepath}/pluginTemp/config.json`),
    JSON.stringify(configJson, null, 2),
    "utf8"
  );
  fs.writeFileSync(
    path.resolve(__dirname, `${basepath}/package.json`),
    JSON.stringify(packageJson, null, 2),
    "utf8"
  );

  const args = isAll
    ? [newFolderFullName, viewAnswer, true, pluginType]
    : [newFolderFullName, viewAnswer];
  return templateChoices
    .find(item => item.value === templateType)
    .handleFun(...args);
}

function mkdirSync(dirname) {
  if (fs.existsSync(dirname)) {
    return true;
  } else {
    //如果父级目录已经创建，然后才能创建子级目录
    if (mkdirSync(sysPath.dirname(dirname))) {
      fs.mkdirSync(dirname);
      return true;
    }
  }
}
